extends Node2D

# 僵尸场景预加载
@export var zombie_scene: PackedScene = preload("res://scene/character/zombie/zombie.tscn")
# 生成配置
@export var spawn_interval_min: float = 2.0  # 最小生成间隔（秒）
@export var spawn_interval_max: float = 5.0  # 最大生成间隔（秒）
@export var max_zombies: int = 20  # 场景中最大僵尸数量
@export var spawn_radius_min: float = 300.0  # 最小生成距离
@export var spawn_radius_max: float = 600.0  # 最大生成距离
# 生成区域配置
@export var spawn_area: Rect2 = Rect2(-1000, -1000, 2000, 2000)  # 默认生成区域
@export var use_fixed_area: bool = false  # 是否使用固定区域而非玩家为中心
@export var map_group: String = "map"  # 地图组名称
@export var max_spawn_attempts: int = 30  # 最大生成尝试次数

# 内部变量
var timer: Timer
var rng                  = RandomNumberGenerator.new()
var player: Node2D       = null
var current_map: TileMapLayer = null
var map_rect: Rect2      = Rect2()

# 僵尸追踪目标组名称
@export var target_group: String = "player"


func _ready():
	# 初始化随机数生成器
	rng.randomize()

	# 寻找玩家
	player = get_tree().get_first_node_in_group(target_group)

	# 寻找地图
	_find_current_map()

	# 创建定时器
	timer = Timer.new()
	add_child(timer)
	timer.one_shot = true
	timer.timeout.connect(_on_spawn_timer_timeout)

	# 开始第一次生成
	_start_spawn_timer()

	# 将自己添加到敌人管理组
	add_to_group("enemy_manager")


func _process(_delta):
	# 定期检查当前地图是否发生变化
	if not current_map or not is_instance_valid(current_map):
		_find_current_map()


# 查找当前地图
func _find_current_map():
	var maps = get_tree().get_nodes_in_group(map_group)
	if maps.size() > 0:
		current_map = maps[0]
		_update_map_rect()
		print("找到当前地图: ", current_map.name)
	else:
		print("没有找到地图，使用默认生成区域")


# 更新地图矩形范围
func _update_map_rect():
	if not current_map:
		return

	# 获取地图使用的单元格
	var used_cells = current_map.get_used_cells()  # 假设我们使用第0层

	if used_cells.size() == 0:
		print("地图没有使用的单元格")
		return

	# 计算地图边界
	var min_x = INF
	var min_y = INF
	var max_x = -INF
	var max_y = -INF

	for cell in used_cells:
		min_x = min(min_x, cell.x)
		min_y = min(min_y, cell.y)
		max_x = max(max_x, cell.x)
		max_y = max(max_y, cell.y)

	# 转换为世界坐标
	var world_min = current_map.map_to_local(Vector2i(min_x, min_y))
	var world_max = current_map.map_to_local(Vector2i(max_x + 1, max_y + 1))  # +1 是因为我们需要包含最后一个单元格

	# 创建矩形
	map_rect = Rect2(
		world_min.x,
		world_min.y,
		world_max.x - world_min.x,
		world_max.y - world_min.y
	)

	print("地图范围已更新: ", map_rect)


# 开始生成计时器
func _start_spawn_timer():
	var next_spawn_time = rng.randf_range(spawn_interval_min, spawn_interval_max)
	timer.start(next_spawn_time)


# 计时器超时处理
func _on_spawn_timer_timeout():
	# 检查是否已达到最大僵尸数量
	var current_zombies = get_tree().get_nodes_in_group("enemies").size()

	if current_zombies < max_zombies:
		spawn_zombie()

	# 重新开始计时器
	_start_spawn_timer()


# 生成僵尸
func spawn_zombie():
	# 检查玩家是否存在
	if not is_instance_valid(player):
		player = get_tree().get_first_node_in_group(target_group)
		if not player:
			return

	# 检查地图是否存在
	if not current_map or not is_instance_valid(current_map):
		_find_current_map()
		if not current_map:
			print("无法生成僵尸：找不到地图")
			return

	# 选择生成位置
	var spawn_position = _get_valid_spawn_position()
	if spawn_position == Vector2.ZERO:
		print("无法找到有效的生成位置")
		return

	# 实例化僵尸
	var zombie_instance = zombie_scene.instantiate()

	# 设置僵尸位置
	zombie_instance.position = spawn_position

	# 将僵尸添加到组
	zombie_instance.add_to_group("enemies")

	# 添加到场景
	add_child(zombie_instance)

	# 输出调试信息
	print("生成了一个僵尸，位置：", spawn_position)


# 获取有效的生成位置
func _get_valid_spawn_position() -> Vector2:
	# 如果没有有效的地图范围，尝试使用默认方法
	if map_rect.size == Vector2.ZERO or not current_map:
		return _get_random_spawn_position()

	var attempts        = 0
	var position_result = Vector2.ZERO
	var is_valid        = false

	while attempts < max_spawn_attempts and not is_valid:
		attempts += 1

		# 根据是否使用固定区域决定生成方式
		if use_fixed_area:
			# 在地图矩形范围内随机选择位置
			position_result = Vector2(
				rng.randf_range(map_rect.position.x, map_rect.position.x + map_rect.size.x),
				rng.randf_range(map_rect.position.y, map_rect.position.y + map_rect.size.y)
			)
		else:
			# 以玩家为中心，在地图范围内生成
			var angle        = rng.randf_range(0, TAU)
			var max_distance = min(spawn_radius_max, _get_max_distance_in_direction(player.position, angle))
			var min_distance = min(spawn_radius_min, max_distance)

			if min_distance >= max_distance:
				min_distance = max_distance * 0.5

			var distance = rng.randf_range(min_distance, max_distance)
			position_result = player.position + Vector2(cos(angle), sin(angle)) * distance

		# 检查位置是否在地图内部
		is_valid = map_rect.has_point(position_result)

		# 检查位置是否是可行走的（非障碍物）
		if is_valid and current_map:
			var map_pos   = current_map.local_to_map(position_result)
			var tile_data = current_map.get_cell_tile_data(map_pos)  # 修复：传入坐标参数

			# 如果没有瓦片数据或瓦片数据表示不可行走，则位置无效
			if not tile_data or (tile_data.get_custom_data("blocked") if tile_data.has_custom_data("blocked") else false):
				is_valid = false

	if not is_valid:
		print("无法在 ", attempts, " 次尝试后找到有效的生成位置")
		return Vector2.ZERO

	return position_result


# 计算从指定位置沿指定角度的最大距离（在地图范围内）
func _get_max_distance_in_direction(start_pos: Vector2, angle: float) -> float:
	if map_rect.size == Vector2.ZERO:
		return spawn_radius_max

	var direction    = Vector2(cos(angle), sin(angle))
	var max_distance = spawn_radius_max

	# 计算与地图边界的交点
	var intersect_distances = []

	# 上边界
	var top_y = map_rect.position.y
	var top_t = (top_y - start_pos.y) / direction.y if direction.y != 0 else INF
	if top_t > 0:
		var top_x = start_pos.x + direction.x * top_t
		if top_x >= map_rect.position.x and top_x <= map_rect.position.x + map_rect.size.x:
			intersect_distances.append(top_t)

	# 下边界
	var bottom_y = map_rect.position.y + map_rect.size.y
	var bottom_t = (bottom_y - start_pos.y) / direction.y if direction.y != 0 else INF
	if bottom_t > 0:
		var bottom_x = start_pos.x + direction.x * bottom_t
		if bottom_x >= map_rect.position.x and bottom_x <= map_rect.position.x + map_rect.size.x:
			intersect_distances.append(bottom_t)

	# 左边界
	var left_x = map_rect.position.x
	var left_t = (left_x - start_pos.x) / direction.x if direction.x != 0 else INF
	if left_t > 0:
		var left_y = start_pos.y + direction.y * left_t
		if left_y >= map_rect.position.y and left_y <= map_rect.position.y + map_rect.size.y:
			intersect_distances.append(left_t)

	# 右边界
	var right_x = map_rect.position.x + map_rect.size.x
	var right_t = (right_x - start_pos.x) / direction.x if direction.x != 0 else INF
	if right_t > 0:
		var right_y = start_pos.y + direction.y * right_t
		if right_y >= map_rect.position.y and right_y <= map_rect.position.y + map_rect.size.y:
			intersect_distances.append(right_t)

	# 找到最小的正交点距离
	if intersect_distances.size() > 0:
		intersect_distances.sort()
		max_distance = min(max_distance, intersect_distances[0])

	return max_distance


# 原始的随机生成位置方法（作为备份）
func _get_random_spawn_position() -> Vector2:
	var position_result: Vector2

	if use_fixed_area:
		# 使用固定区域
		position_result = Vector2(
			rng.randf_range(spawn_area.position.x, spawn_area.position.x + spawn_area.size.x),
			rng.randf_range(spawn_area.position.y, spawn_area.position.y + spawn_area.size.y)
		)
	else:
		# 使用玩家为中心
		if player:
			# 生成随机角度和距离
			var angle    = rng.randf_range(0, TAU)
			var distance = rng.randf_range(spawn_radius_min, spawn_radius_max)

			# 计算位置
			position_result = player.position + Vector2(cos(angle), sin(angle)) * distance
		else:
			# 如果没有玩家，使用默认生成区域
			position_result = Vector2(
				rng.randf_range(spawn_area.position.x, spawn_area.position.x + spawn_area.size.x),
				rng.randf_range(spawn_area.position.y, spawn_area.position.y + spawn_area.size.y)
			)

	return position_result


# 公共方法：手动生成指定数量的僵尸
func spawn_zombies(count: int):
	for i in range(count):
		spawn_zombie()


# 清除所有僵尸
func clear_all_zombies():
	var zombies = get_tree().get_nodes_in_group("enemies")
	for zombie in zombies:
		zombie.queue_free()


# 设置生成参数
func set_spawn_parameters(interval_min: float, interval_max: float, max_count: int):
	spawn_interval_min = interval_min
	spawn_interval_max = interval_max
	max_zombies = max_count


# 暂停/恢复生成
func set_spawning_active(active: bool):
	if active:
		if timer.is_stopped():
			_start_spawn_timer()
	else:
		timer.stop()
